#!/usr/bin/env python3
import os
import re
import subprocess
from pathlib import Path
import sys
import argparse
import shutil


def extract_dependencies(spec_file: Path) -> set:
    """使用rpmspec从spec文件中提取Requires和BuildRequires依赖项"""
    dependencies = set()
    try:
        # 获取Requires和BuildRequires依赖
        # 分别查询Requires和BuildRequires依赖
        req_result = subprocess.run(
            ['rpmspec', '-q', '--requires', '--define', 'ros_distro loong', str(spec_file)],
            capture_output=True, text=True, check=True
        )
        build_req_result = subprocess.run(
            ['rpmspec', '-q', '--buildrequires', '--define', 'ros_distro loong', str(spec_file)],
            capture_output=True, text=True, check=True
        )

        # 合并两次查询结果
        all_deps = (req_result.stdout + build_req_result.stdout).splitlines()
        for dep in all_deps:
            dep = dep.strip()
            if dep and not dep.startswith('agiros-'):
                dependencies.add(dep)

    except subprocess.CalledProcessError as e:
        print(f"解析spec文件 {spec_file} 时出错: {e.stderr}")
    except Exception as e:
        print(f"处理spec文件 {spec_file} 时出错: {e}")
    return dependencies


def is_dependency_installed(dep):
    """检查依赖项是否已安装"""
    try:
        # 使用rpm -q检查包是否安装
        result = subprocess.run(
            ['rpm', '-q', dep],
            check=False,
            capture_output=True,
            text=True
        )
        # 返回码为0表示已安装
        return result.returncode == 0
    except Exception as e:
        print(f"检查依赖项 {dep} 时出错: {e}")
        return False

def configure_third_party_yum_repo():
    """配置第三方yum源"""
    repo_path = Path("/etc/yum.repos.d/the_third_package.repo")
    if not repo_path.exists():
        repo_content = """[third-package-oemaker]
name=oemaker-third-packages
baseurl=https://eulermaker.compass-ci.openeuler.openatom.cn/api/ems1/repositories/the-third-packages/openEuler%3A24.03-LTS/x86_64/
enabled=1
gpgcheck=0
"""
        try:
            repo_path.write_text(repo_content)
            print(f"创建第三方yum源配置文件: {repo_path}")
        except Exception as e:
            print(f"创建yum源配置文件失败: {e}")
            sys.exit(1)
    else:
        print(f"第三方yum源配置文件已存在: {repo_path}")
    
    # 清理并重新构建yum缓存
    try:
        print("清理yum缓存...")
        subprocess.run(['yum', 'clean', 'all'], check=True, capture_output=True, text=True)
        print("重新构建yum缓存...")
        subprocess.run(['yum', 'makecache'], check=True, capture_output=True, text=True)
        print("yum源配置完成")
    except subprocess.CalledProcessError as e:
        print(f"执行yum命令失败: {e.stderr}")
        sys.exit(1)


def install_spec_dependencies(spec_dependencies: dict):
    """安装依赖项并按spec文件统计失败情况"""
    spec_failed_deps = {}  # 键: spec文件路径, 值: 失败的依赖项列表
    total_success = 0
    total_failed = 0
    total_skipped = 0

    for spec_file, dependencies in spec_dependencies.items():
        print(f"\n处理 {spec_file} 的依赖项...")
        success_count = 0
        fail_count = 0
        skipped_count = 0
        failed_deps = []

        for dep in dependencies:
            if is_dependency_installed(dep):
                print(f"依赖项 {dep} 已安装，跳过。")
                skipped_count += 1
                total_skipped += 1
                continue
            print(f"正在安装依赖项: {dep}")
            cmd = ['yum', 'install', '-y', dep]
            try:
                result = subprocess.run(
                    cmd,
                    check=True,
                    capture_output=True,
                    text=True
                )
                print(f"依赖项 {dep} 安装成功！")
                success_count += 1
                total_success += 1
            except subprocess.CalledProcessError as e:
                print(f"依赖项 {dep} 安装失败: {e.stderr}")
                fail_count += 1
                total_failed += 1
                failed_deps.append(dep)

        if failed_deps:
            spec_failed_deps[spec_file] = failed_deps
            print(f"{spec_file} 有 {fail_count} 个依赖项安装失败。")
        else:
            print(f"{spec_file} 的所有依赖项安装成功。")

    # 输出总体统计
    print(f"\n所有依赖项处理完成: 成功 {total_success} 个, 失败 {total_failed} 个, 已跳过 {total_skipped} 个")
    
    # 输出每个spec文件的失败情况
    if spec_failed_deps:
        print("\n安装失败的依赖项按spec文件统计:")
        for spec_file, deps in spec_failed_deps.items():
            print(f"{spec_file}: {len(deps)} 个失败依赖项 - {', '.join(deps)}")
        
        # 汇总所有失败的依赖项
        all_failed_deps = set()
        for deps in spec_failed_deps.values():
            all_failed_deps.update(deps)
        
        print(f"\n所有失败的依赖项汇总 ({len(all_failed_deps)} 个): {', '.join(all_failed_deps)}")
        sys.exit(1)
    else:
        print("\n所有依赖项均安装成功！")

def main():
    parser = argparse.ArgumentParser(description='Install dependencies from RPM spec files.')
    parser.add_argument('--spec-directory', type=Path, default=Path.cwd() / 'build' / 'SPECS',
                        help='Directory containing RPM spec files (default: ./build/SPECS)')
    args = parser.parse_args()
    spec_directory = args.spec_directory

    # 安装rpmbuild命令
    if shutil.which('rpmbuild') is None:
        print("⚠️ rpmbuild 未安装，正在安装...")
        try:
            subprocess.run(['yum', 'install', '-y', 'rpm-build'], check=True)
            print("✅ rpmbuild 安装成功")
        except subprocess.CalledProcessError as e:
            print("❌ rpmbuild 安装失败:", e)
            sys.exit(1)

    # 检查目录是否存在
    if not spec_directory.exists() or not spec_directory.is_dir():
        print(f"目录 {spec_directory} 不存在。请检查路径。")
        sys.exit(1)

    # 获取所有.spec文件
    spec_files = list(spec_directory.glob("*.spec"))
    if not spec_files:
        print(f"在目录 {spec_directory} 下未找到任何 .spec 文件。")
        sys.exit(1)

    # 收集所有依赖项，按spec文件分组
    spec_dependencies = {}
    for spec_file in spec_files:
        print(f"处理文件: {spec_file}")
        deps = extract_dependencies(spec_file)
        spec_dependencies[spec_file] = deps
        print(f"{spec_file} 中的依赖项处理完成。")

    # 配置第三方yum源
    configure_third_party_yum_repo()
    
    # 安装依赖项并统计
    install_spec_dependencies(spec_dependencies)
    print("所有 .spec 文件的依赖项处理完成。")


if __name__ == "__main__":
    main()